/*
 * Copyright (c) 2019.  鼎捷软件股份有限公司.All rights reserved.
 */

package com.digiwin.dap.middleware.entity;

import com.digiwin.dap.middleware.exception.BusinessException;
import com.digiwin.dap.middleware.util.ReflectionUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.persistence.Column;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.constraints.NotNull;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 描述业务主键
 */
public class UnionKey {
    static Pattern regex = Pattern.compile("[A-Z]+");
    private Class<?> entityClass;
    private ArrayList<String> fields = new ArrayList<>();
    private ArrayList<String> tableFields = new ArrayList<>();

    /**
     * @return
     */
    public static UnionKey create() {
        return new UnionKey();
    }

    public UnionKey apply(@NotNull Class<?> entityClass) {
        Assert.notNull(entityClass, "entityClass 不能为null");
        this.entityClass = entityClass;
        return this;
    }


    /**
     * 添加业务主键的字段。注意顺序
     *
     * @param name
     * @return
     */
    public UnionKey add(@NotNull String name) {
        if (StringUtils.isEmpty(name)) {
            throw new IllegalArgumentException("name 不能为空");
        }
        if (fields.contains(name)) {
            throw new IllegalArgumentException("存在重复的值：" + name);
        }
        Assert.notNull(entityClass, "entityClass 不能为null,请先调用apply方法");

        Field field = ReflectionUtils.getDeclaredField(this.entityClass, name);
        if (field == null){
            throw new BusinessException(String.format("%s 上不存在属性%s", entityClass, name));
        }

        this.fields.add(name);
        String columnName = name;
        Column column = field.getAnnotation(Column.class);
        if (column != null && !StringUtils.isEmpty(column.name())) {
            columnName = column.name().toUpperCase();
            columnName = columnName.replace("[", "`");
            columnName = columnName.replace("]", "`");
            this.tableFields.add(columnName);
        } else {

            Matcher matcher = UnionKey.regex.matcher(columnName);
            if (matcher.find()) {
                columnName = matcher.replaceAll("_$0");
            }
            columnName = columnName.toUpperCase();
            this.tableFields.add(columnName);
        }
        return this;
    }

    /**
     * 清楚
     */
    public void clear() {
        this.fields.clear();
        this.tableFields.clear();
    }

    /**
     * 获取查询的sql
     *
     * @return
     */
    public String getSelectSql() {
        StringBuilder sql = new StringBuilder();
        for (int i = 0; i < tableFields.size(); i++) {
            sql.append(tableFields.get(i));
            if (i < tableFields.size() - 1) {
                sql.append(",");
            }
        }
        return sql.toString();
    }

    /**
     * 拼凑where条件
     *
     * @param values 如果值为null，也必须传入null
     * @return
     */
    public String getWhereSql(Object... values) {
        if (values == null || values.length != fields.size()) {
            throw new IllegalArgumentException("值不能为空或者可能小于或者大于主键的数量");
        }

        StringBuilder sql = new StringBuilder();
        for (int i = 0; i < tableFields.size(); i++) {
            Object paraValue = values[i];
            String paraName = tableFields.get(i);

            if (paraValue == null) {
                sql.append(String.format("ISNULL(%s)", paraName));
            } else {

                if (paraValue instanceof Integer
                        || paraValue instanceof Long
                        || paraValue instanceof Double
                        || paraValue instanceof Boolean) {
                    sql.append(String.format("%s = %s", paraName, paraValue));
                } else {
                    sql.append(String.format("%s = '%s'", paraName, paraValue));
                }
            }
            if (i < fields.size() - 1) {
                sql.append(" AND ");
                ;
            }
        }
        return sql.toString();

    }

    /**
     * 生成支持jpa自定义查询的查询类
     *
     * @param values
     * @param <T>
     * @return
     */
    public <T extends BaseEntity> Predicate getSpecification(Root<T> root, CriteriaQuery<?> cq, CriteriaBuilder cb, Object... values) {
        if (values == null || values.length != fields.size()) {
            throw new IllegalArgumentException("值不能为空或者可能小于主键的数量");
        }
        Predicate predicate = cb.conjunction();
        for (int i = 0; i < fields.size(); i++) {
            Object paraValue = values[i];
            String paraName = fields.get(i);
            if (paraValue == null) {
                predicate.getExpressions().add(cb.isNull(root.get(paraName)));
            } else {

                if (paraValue instanceof Integer
                        || paraValue instanceof Long
                        || paraValue instanceof Double
                        || paraValue instanceof Boolean) {
                    predicate.getExpressions().add(cb.equal(root.get(paraName).as(long.class), paraValue));
                } else {
                    predicate.getExpressions().add(cb.equal(root.get(paraName).as(String.class), paraValue));
                }
            }
        }
        return predicate;
    }


}
